textbtree: short-circuit visibility check when possible
authorChristian Hergert <chergert@redhat.com>
Wed, 18 Mar 2020 18:32:46 +0000 (11:32 -0700)
committerChristian Hergert <chergert@redhat.com>
Wed, 18 Mar 2020 18:32:46 +0000 (11:32 -0700)
If we have never seen a GtkTextTag in the GtkTextTagTable with the
invisible bit set, then we do not need to go through the process of
checking the accumulated tags.

Not using invisible tags is overwhelmingly the common case.

gtk/gtktextbtree.c
gtk/gtktexttagtable.c
gtk/gtktexttagtableprivate.h

index 1ab7878539f77ad1add2dd3d67fc53d82eed14b3..65aae142e1be32cd7dcc4be45e34cecfeef0e20f 100644 (file)
@@ -60,7 +60,7 @@
 #include "gtktextbufferprivate.h"
 #include "gtktexttag.h"
 #include "gtktexttagprivate.h"
-#include "gtktexttagtable.h"
+#include "gtktexttagtableprivate.h"
 #include "gtktextlayoutprivate.h"
 #include "gtktextiterprivate.h"
 #include "gtkdebug.h"
@@ -2491,6 +2491,13 @@ _gtk_text_btree_char_is_invisible (const GtkTextIter *iter)
 
   line = _gtk_text_iter_get_text_line (iter);
   tree = _gtk_text_iter_get_btree (iter);
+
+  /* Short-circuit if we've never seen a visibility tag within the
+   * tag table (meaning everything must be visible).
+   */
+  if G_LIKELY (!_gtk_text_tag_table_affects_visibility (tree->table))
+    return FALSE;
+
   byte_index = gtk_text_iter_get_line_index (iter);
 
   numTags = gtk_text_tag_table_get_size (tree->table);
index 81a852ccc31390943b1fc2b14ac77fc7eb97d328..c28621edd689bb208cbaa6ec8f287e295c7d17b4 100644 (file)
@@ -88,6 +88,8 @@ struct _GtkTextTagTablePrivate
   GSList     *buffers;
 
   gint anon_count;
+
+  guint seen_invisible : 1;
 };
 
 enum {
@@ -180,6 +182,22 @@ gtk_text_tag_table_init (GtkTextTagTable *table)
   table->priv->hash = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
+static void
+check_visible (GtkTextTagTable *table,
+               GtkTextTag      *tag)
+{
+  if (table->priv->seen_invisible)
+    return;
+
+  if (tag->priv->invisible_set)
+    {
+      gboolean invisible;
+
+      g_object_get (tag, "invisible", &invisible, NULL);
+      table->priv->seen_invisible = invisible;
+    }
+}
+
 /**
  * gtk_text_tag_table_new:
  * 
@@ -301,6 +319,8 @@ gtk_text_tag_table_add (GtkTextTagTable *table,
   g_assert (size > 0);
   tag->priv->priority = size - 1;
 
+  check_visible (table, tag);
+
   g_signal_emit (table, signals[TAG_ADDED], 0, tag);
   return TRUE;
 }
@@ -490,5 +510,12 @@ _gtk_text_tag_table_tag_changed (GtkTextTagTable *table,
                                  GtkTextTag      *tag,
                                  gboolean         size_changed)
 {
+  check_visible (table, tag);
   g_signal_emit (table, signals[TAG_CHANGED], 0, tag, size_changed);
 }
+
+gboolean
+_gtk_text_tag_table_affects_visibility (GtkTextTagTable *table)
+{
+  return table->priv->seen_invisible;
+}
index 0a8401e695a05a87057bb682f6f2e9753ad7a950..4bf0d5773c9aa8db2f9527951c9e6c4e2d79cf12 100644 (file)
 
 G_BEGIN_DECLS
 
-void _gtk_text_tag_table_add_buffer    (GtkTextTagTable *table,
-                                        gpointer         buffer);
-void _gtk_text_tag_table_remove_buffer (GtkTextTagTable *table,
-                                        gpointer         buffer);
-void _gtk_text_tag_table_tag_changed   (GtkTextTagTable *table,
-                                        GtkTextTag      *tag,
-                                        gboolean         size_changed);
+void     _gtk_text_tag_table_add_buffer         (GtkTextTagTable *table,
+                                                 gpointer         buffer);
+void     _gtk_text_tag_table_remove_buffer      (GtkTextTagTable *table,
+                                                 gpointer         buffer);
+void     _gtk_text_tag_table_tag_changed        (GtkTextTagTable *table,
+                                                 GtkTextTag      *tag,
+                                                 gboolean         size_changed);
+gboolean _gtk_text_tag_table_affects_visibility (GtkTextTagTable *table);
 
 G_END_DECLS